Design for mpMUD Version Four

(Note to self: this is not a formal specification, don't waste time being overly rigorous in description)

Things needed to be specified:
  * Inheritance
  * Exception objects in 5.004



%%%% Definitions

"library": Code that is not part of the core - e.g. in v3, modules and world.

"core-class": one of several classes of library-extendable objects.



%%%% Standard Object Interfaces

These are interfaces for core-level objects to implement, not library code - i.e. the library's objects are built on top of objects implementing these interfaces, and also the 'intermediate layer' (proxy classes) may impose security restrictions.

Unless otherwise noted, all of these methods might call library-level code. Obhject

%% Attributed Objects

KIND in parameter list means namespace.

All of these methods may produce exceptions due to security restrictions, incorrect types, etc.

Namespace and attribute names may contain any of the characters in the "printable" ASCII character set - [\x20-\x7E] or [ -~]. They can be from 0 to 1023 characters in length. This length restruction is specified to prevent excessive memory usage and allow the storage of attribute names in fixed-length fields. (Yes, it is fine to have an attribute named '' in namespace '')

Instance Methods:
  getAttribute(KIND, NAME[, DEFAULT])
  Returns the value of the specified attribute. If the object supports inheritance of attributes, it should return an inherited value if there is one. If no value can be found, DEFAULT or undef is returned.
  Consider: Difference between an attribute completely not existing (returns DEFAULT) and an attribute with a value of undef. Should this be revealed?

  setAttribute(KIND, NAME, VALUE)
  Sets the attribute to the VALUE. 
  
  deleteAttribute(KIND, NAME)
  Deletes the attribute and returns the old value.
  
  listAttributes(KIND[, INHERIT])
  Returns a list of the attributes of this object in the specified namespace. INHERIT is a flag, if true the list includes inherited attributes. Defaults to false.

  listNamespaces([INHERIT])
  Returns a list of the namespaces for which this object has one or more attributes.
  INHERIT is used in the same way as above.

  getAttr(NAME[, DEFAULT])
  setAttr(NAME, VALUE)
  deleteAttr(NAME)
  listAttrs([INHERIT])
  Just like the above four, except they assume the namespace "" (empty string).
  
** On second thought, the DEFAULT parameter will not be implemented - for now.
  
All of these methods may have additional parameters added later.

%% Object Creation and Inheritance

This interface is for objects which implement prototype-based inheritance and are not automatically destroyed.

This is something to consider carefully...

Methods:
  spawnObject()
  Creates an object that inherits from the object this method is called on, with no attributes otherwise.

  destroyObject()
  Destroys this object immediately.
  
%% Storage Class

Instance OR Class Methods:
  object_register(OBJ, KEY)
  Registers an object with the storage, making it persistent. KEY is the suggested access key for the object, which should be a string; this argument may be ignored.
  
  object_changed(OBJ)
  
  object_unregister(OBJ)
  
  object_get_key(OBJ)
  Returns the access key for this object.
  
  object_registered_time(OBJ)
  Returns the time at which the object was registered.
  
  obj(KEY)
  Returns a proxy for the object identified by KEY.

%% Persistent Object

Instance Methods:
  storage_get_data(TYPE)
  Return the serialized form of the object for storage. It should be a reference to a scalar, blessed into a class that has the instance method storage_create_with_data. TYPE will be either undef or 'text'. If it is 'text', then the object should serialize into a form readable and editable with a text editor. All other values should be treated as undef.

  storage_create_from_data(TYPE)
  Recreate an object with the stored data and return it. ($self is the result of storage_get_data). The storage cookie should be restored. It's okay to return the DATA without copying it. TYPE will be the same value as was passed to storage_get_data.
  
  storage_set_cookie()
  Set the storage cookie; this is an opaque value which is set by the Storage for this object, usually to keep track of which stored object goes with which in-memory object.

  storage_get_cookie()
  Return the storage cookie.
  
%%%% Object Reference/Proxy Behavior

Issues regarding objects and object references:
  * Objects may become nonexistent at any time
  * How to support naming at the core level, when most of naming semantics work at lib level?
  * If a reference is "by name", then an object may become re-existent, therefore object refs may need to be kept around.
  * Refs must be serializable
  * One might end up with a persisted reference to a non-persistent object

Notes:
  * Perhaps refs should indicate whether they are permanently or temporarily invalid
  * Should have a standard "namespace" for ref methods
  * Refs might actually be the object, if the object does not need to keep its identity and is immutable.
  * Should ref classes have a standard base?
  
%%%% Packages & Classes

Notes:
  * We should have a standard prefix, but should it be letters (e.g. "M") or a full package? And if a package, what to call it? "mpMUD::"? ick.
  * MConnection::Nil will go away, as we'll have refs instead.
  * Connections must be implementable by library objects so that persistent "AI connections" are possible
  * Goal worth considering: as few mentions of package names as possible.

New package list (prefixes omitted, non-OO indicated by &):
  Connection (inherits Obj::Attributed)
    Handle (socket or stdin/out etc.)
    Telnet
  Context (arbitrary execution context info)
  &CoreTools
  DefList (avoid using this till it's really needed...)
  FS (platform-independent filesystem access)
  &Freezer (maybe this should be part of coretools, or maybe OO?)
  IOManager (base class)
  IOManager::Select (select())
  IOManager::Poll   (poll()  )
  Obj::Attributed  (base class for objects implementing the above attribute interface, also provides persistence interface)
  Obj::Event (like current MEvent::Message)
  Proxy
  Proxy::Key
  Proxy::Name
  Scheduler (pretty much same as now)
  StorableSub
  Storage::DBI (uses any DBI database)
  Storage::Chunked (like current MObjectDB)
  Storage::NamedFiles (replaces current modules)
  Storage::Simble (Bruce's Simble library)
  Storage::Ephemeral (holds everything in memory. used for non-persistent objs that need to be referenced indirectly)
  Transaction (will not do anything initially, but will have hooks into other systems for implementing transactions)
  
Old things that aren't carried over and why:
  * MInitializable: should have a system for avoiding the interdependence that MInitializable was a basis for
  * MTerminal::*: should be implemented at lib level
  * MModules: we won't have modules any more, just objects
  
These things should be defined by the library:
  * interface object
  * terminal object
  
%%%% Security Issues

%% Logins and evaluation

 - Administrators need to be able to compile method source on-the-fly.
 - The Safe module is not safe and places restrictions that prevent its usage in mpMUD.
 - Therefore, we must make certain that administrators are genuine.

 - Logging in over any insecure network connection must be disabled.
 - Connections from the same machine should be OK.
 - There is no SSH server for Perl.
 - Therefore, we must allow only local connections. Secure remote access may be obtained by logging in over SSH, then connecting to the mud locally.

 - Simplification of the above method (for Unix): Create an account whose login shell is a script that opens telnet or a pipe to mpMUD.